using System;
using System.Xml;
using System.Net;
using System.Data;
using MyClever.Lib;

namespace MyClever.DefaultPlugins
{
    public class ReadRssFeed : MissionPlugin
    {
        [Package(Direction.Input, "Defines the rss-feeds you like to subscribe for.")]
        enum URLInfo
        {
            [Column(typeof(Int32), "Numbers of feeds to store.",
                DefaultValue= "200")]
            NumFeedItems,
            [Column(typeof(string), "URL where you get the rss-feed from.", 
                Validation = "IsURL")]
            URL,
            [Column(typeof(string), "Sometimes you need a username to get access to the rss-feed.")]
            Username,
            [Column(typeof(string), "Sometimes you need a password to get access to the rss-feed.")]
            Password
        }

        [Package(Direction.Output, "Defines the content of the expected rss-feeds.")]
        enum RSSOutput
        {
            [Column(typeof(string), "A unique identifier for the item.")]
            Guid,
            [Column(typeof(string), "Headline of the feed item.")]
            Title,
            [Column(typeof(string), "Link to the website of this feed item.")]
            Link,
            [Column(typeof(string), "The article/text itself.")]
            Description,
            [Column(typeof(string), "The e-mail address of the author.")]
            Author,
            [Column(typeof(string), "One or more categories the item belongs to.")]
            Category,
            [Column(typeof(string), "The link to comments about that item.")]
            Comments,
            [Column(typeof(string), "The last-publication date for the item.")]
            PubDate,
            [Column(typeof(string), "A third-party source for the item.")]
            Source,
            [Column(typeof(string), "The URL to the media file.")]
            EnclosureURL,
            [Column(typeof(string), "The length (in bytes) of the media file")]
            EnclosureLength,
            [Column(typeof(string), "The type of media file.")]
            EnclosureType,
            [Column(typeof(string), "The direct URL to the media object")]
            Media_ContentURL,
            [Column(typeof(string), "The number of bytes of the media object")]
            Media_ContentFileSize,
            [Column(typeof(string), "The standard MIME type of the object")]
            Media_ContentType,
            [Column(typeof(string), "The type of object (image | audio | video | document | executable)")]
            Media_ContentMedium,
            [Column(typeof(string), "The number of audio channels in the media object.")]
            Media_ContentChannels,
            [Column(typeof(string), "The number of seconds the media object plays")]
            Media_ContentDuration,
            [Column(typeof(string), "The height of the media object.")]
            Media_ContentHeight,
            [Column(typeof(string), "The width of the media object.")]
            Media_ContentWidth,
            [Column(typeof(string), "The primary language encapsulated in the media object.")]
            Media_ContentLang,
            [Column(typeof(string), "The URL of the player console that plays the media.")]
            Media_PlayerURL,
            [Column(typeof(string), "The height of the browser window that the URL should be opened in.")]
            Media_PlayerHeight,
            [Column(typeof(string), "The width of the browser window that the URL should be opened in.")]
            Media_PlayerWidth,
            [Column(typeof(string), "Specifies the url of the thumbnail.")]
            Media_ThumbnailURL,
            [Column(typeof(string), "Specifies the height of the thumbnail.")]
            Media_ThumbnailHeight,
            [Column(typeof(string), "Specifies the width of the thumbnail.")]
            Media_ThumbnailWidth
        }

        [Plugin(PluginDevStatus.Production, "Fetch the subscribed RSS Feed.")]
        public ReadRssFeed()
        {
        }

        public override void Initialize()
        {
            
            //This is the first Function called by the host...
            //Put anything needed to start with here first
        }

        public override void Dispose()
        {
            //Put any cleanup code in here for when the program is stopped
        }

        /// <summary>
        /// Generate new Source-content.
        /// </summary>
        protected override void Work()
        {            
            DataTableReader urlInfoPackage = this.GetDataReader(typeof(URLInfo));
            while (urlInfoPackage.Read())
            {
                Uri rssURL = new Uri(urlInfoPackage[URLInfo.URL.ToString()].ToString());

                this.AddNewLoggingMessage(typeof(URLInfo), String.Format("read feed: {0}", rssURL.AbsoluteUri));

                HttpWebRequest request = (HttpWebRequest)WebRequest.Create(rssURL.AbsoluteUri);
                //is important for Facebook-Feeds
                request.UserAgent = "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.0)"; 

                // are there any given credentials?
                if (false == String.IsNullOrEmpty(urlInfoPackage[URLInfo.Username.ToString()].ToString()) && false == String.IsNullOrEmpty(urlInfoPackage[URLInfo.Password.ToString()].ToString()))
                {
                    request.Credentials = new NetworkCredential(urlInfoPackage[URLInfo.Username.ToString()].ToString(), urlInfoPackage[URLInfo.Password.ToString()].ToString());
                }
                
                WebResponse response = request.GetResponse();

                //Fetch the subscribed RSS Feed
                XmlDocument RSSXmlDocument = new XmlDocument();
                RSSXmlDocument.Load(response.GetResponseStream());

                XmlNodeList RSSNodeItems = RSSXmlDocument.SelectNodes("rss/channel/item");

                int numFeeds = 0;
                foreach (XmlNode RSSNodeItemOn in RSSNodeItems)
                {
                    if (numFeeds < Convert.ToInt32(urlInfoPackage[URLInfo.NumFeedItems.ToString()]))
                    {
                        DataRow newRow = this.CreateNewRowFromPackage(typeof(RSSOutput));

                        foreach (string rssFeedElementOn in Enum.GetNames(typeof(RSSOutput)))
                        {
                            XmlNode rssSubNode = RSSNodeItemOn.SelectSingleNode(rssFeedElementOn.ToLower());
                            newRow[rssFeedElementOn] = (rssSubNode != null ? rssSubNode.InnerText : "");
                        }

                        //is there any media content?
                        XmlNode enclosureSubNode = RSSNodeItemOn.SelectSingleNode("enclosure");
                        if (null != enclosureSubNode)
	                    {            
                            newRow["EnclosureURL"] = (enclosureSubNode.Attributes["url"] != null ? enclosureSubNode.Attributes["url"].Value : "");
                            newRow["EnclosureLength"] = (enclosureSubNode.Attributes["length"] != null ? enclosureSubNode.Attributes["length"].Value : "");
                            newRow["EnclosureType"] = (enclosureSubNode.Attributes["type"] != null ? enclosureSubNode.Attributes["type"].Value : "");   
                        }

                        //is there any media content?
                        XmlNamespaceManager nsmgr = new XmlNamespaceManager(RSSXmlDocument.NameTable);
                        nsmgr.AddNamespace("media", "http://search.yahoo.com/mrss/");

                        XmlNodeList mediaNodes = RSSNodeItemOn.SelectNodes("media:group/media:*", nsmgr);
                        foreach (XmlNode mediaNodeOn in mediaNodes)
                        {
                            string mediaNodeName = mediaNodeOn.Name.Substring(mediaNodeOn.Name.IndexOf(':') + 1);

                            foreach (XmlAttribute attributeOn in mediaNodeOn.Attributes)
                            {
                                string columnName = "Media_" + mediaNodeName + attributeOn.Name;

                                if (true == newRow.Table.Columns.Contains(columnName) && true == String.IsNullOrEmpty((string)newRow[columnName]))
                                {
                                    newRow[columnName] = attributeOn.Value;
                                }           
                            }
                        }
                
                        this.AddNewRowToPackage(typeof(RSSOutput), newRow);
                        numFeeds++;
                    }
                }
            }  
        }
    }
}
